import java.util.IdentityHashMap;

public class Compound extends Term {
    String name; int arity; Term[] args;
    
    public Compound(String name, Term... args) {
        this.name = name;
        this.arity = args.length;
        this.args = args;
        this.kind = Kind.COMPOUND;
    }
    
    public Compound(Stack<Term> terms) {
        this.name = ((Compound)terms.head.dereference()).name;
        this.arity = terms.height;
        this.args = new Term[arity];
        terms = terms.tail;
        for(int i = 0; i < arity; i++) {
            args[i] = terms.head;
            terms = terms.tail;
        }
        this.kind = Kind.COMPOUND;
    }
    
    public boolean contains(Term t) {
        Term s;
        for(int i = 0; i < arity; i++) {
            s = args[i].dereference();
            if(t == s || s.contains(t))
                return true;
        }
        return false;
    }
    
    public Term copy_term(IdentityHashMap<Term,Term> map) {
        Stack<Term> copiedArgs = null;
        for(int i = arity-1; i >= 0; i--) {
            copiedArgs = new Stack<Term>(args[i].copy_term(map),copiedArgs);
        }
        return new Compound(new Stack<Term>(this,copiedArgs));
    }
    
    public String toString() {
        String s = name;
        if(arity > 0) {
            s += "(";
            for(int i = 0; i < arity; i++) {
                s += args[i];
                if(i != arity-1) {
                    s += ", ";
                }
            }
            s += ")";
        }
        return s;
    }
    
    public static Compound toPrologString(String s) {
        Compound c = new Compound("[]");
        for(int i = s.length()-1; i >= 0; i--) {
            c = new Compound(".", new Compound(""+(int)s.charAt(i)), c);
        }
        return c;
    }
    
    public Stack<Term> fromPrologList() {
        if(arity == 0 && name.equals("[]")) {
            return null;
        }
        else if(arity == 2 && name.equals(".")) {
            return new Stack<Term>(args[0], args[1].fromPrologList());
        }
        else {
            return null; // :/
        }
    }
    
    public Compound fromPrologString() {
        Stack<Term> codes = fromPrologList();
        String s = "";
        while(codes != null) {
            s = s + (char)Integer.parseInt(((Compound)codes.head).name);
            codes = codes.tail;
        }
        return new Compound(s);
    }
}

